package Server;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.mortbay.util.ajax.Continuation;

import Messages.Msg;
import Messages.StopMsg;

import WizardInstall.ServerDetails;
/**
 * this class is sending data to all the clients, and open each new client new thread in 
 * thread pool
 * @author Liel && Guy
 *
 */
public class SendInfo implements Runnable{
	ServerSocket providerSocket;
	String serverFilesPath;
	Socket connection = null;
	HashMap<String, File> filesHash;
	HashMap<String, Continuation> continuation;
	HashMap<String, ArrayList<Msg>> messagesToClient;
	int currentFileId;
	int port = 8899;
	int maxOfExecutors = 10;
	//thread pool of all the clients that are connecting to the server
	private ExecutorService clientRequestPool= Executors.newFixedThreadPool(maxOfExecutors);

	private static class Holder{
		volatile static SendInfo sendInfoSingelton=new SendInfo();
	}
	private SendInfo() {
		serverFilesPath = new String(ServerDetails.getServerDetailInstance().getServerFilePath()+"\\");
		filesHash = new HashMap<String, File>();
		continuation = new HashMap<String, Continuation>();
		currentFileId = 1;
		messagesToClient = new HashMap<String, ArrayList<Msg>>();
	}
	/**
	 * get instance of the class
	 * @return send info singelton
	 */
	public static SendInfo getInstance()  {
		//return the singelton
		return Holder.sendInfoSingelton;
	}
	/**
	 * this is the main method, waiting for connection and save it in thread pool 
	 */
	public void run()
	{
		try{
			providerSocket = new ServerSocket(port, 10);
			while (true){
				//2. Wait for connection
				System.out.println("Waiting for connection");
				connection = providerSocket.accept();
				clientRequestPool.execute(new SendToClientProtocol(connection));
			}
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
		}
		finally
		{	
			//4: Closing connection
			try
			{
				if (providerSocket!=null)
					providerSocket.close();
			}
			catch(IOException ioException)
			{
				ioException.printStackTrace();
			}
		}
	}
	/**
	 * get the message for the user
	 * @param userName - wanted user name
	 * @return - the message
	 */
	public Msg getMessage(String userName){
		ArrayList<Msg> messages = messagesToClient.get(userName);
		Msg msg;
		//if there is no message send stop 
		if (messages==null || messages.isEmpty()){
			msg = new StopMsg();
		}
		else{
			msg = messages.get(0);
			messages.remove(0);
			messagesToClient.put(userName, messages);
		}
		return msg;

	}
	/**
	 * add message to user's messages array
	 * @param userName - wanted user name
	 * @param msg - the wanted message
	 */
	public void addMessage(String userName, Msg msg){
		ArrayList<Msg> message= messagesToClient.get(userName);
		if (message==null){//create new array
			message = new ArrayList<Msg>();
		}
		message.add(msg);
		messagesToClient.put(userName, message);
	}
	/**
	 * check if there are messages for user
	 * @param userName - user name
	 * @return true if there are no messages, false o.w
	 */
	public boolean isEmpty(String userName){
		ArrayList<Msg> message= messagesToClient.get(userName);
		if (message==null || message.isEmpty())
			return true;
		return false;
	}
}
